/**
 * RPicker.java ##copyright## This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any later version. This
 * library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details. You should have received a copy of the GNU Lesser
 * General Public License along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 * 
 * @author ##author##
 * @modified ##date##
 * @version ##version##
 */
package fiveagon.draw;

import geomerative.RGeomElem;
import geomerative.RPoint;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import processing.core.PApplet;

public class RPicker<E extends RGeomElem> implements Iterable<E> {
  private final PApplet parent;
  private final RPoint mouse = new RPoint();

  private final Collection<E> elementCollection;
  private final List<E> pickerList = new ArrayList<E>();
  private E pickerElement = null;

  public RPicker(PApplet parent, Collection<E> elementCollection) {
    this.parent = parent;
    this.elementCollection = elementCollection;
  }

  public void press() {
    if (pickerSelect()) {

    } else {
      clear();
    }
  }

  private boolean pickerSelect() {
    mouse.x = parent.mouseX;
    mouse.y = parent.mouseY;

    for (E element : elementCollection) {
      if (element.contains(mouse)) {
        add(element);
        return true; // pick the bottom-most layer
      }
    }
    return false;
  }

  private void add(E element) {
    pickerElement = element;
    if (!pickerList.contains(pickerElement)) { // Only need one copy
      pickerList.add(pickerElement);
    }
  }

  public final void drag(int keyCodeButton) {
    if (parent.keyPressed && parent.keyCode == keyCodeButton) {
      dragAll();
    } else {
      drag();
    }
  }

  public void drag() {
    if (pickerElement != null) {
      int dX = parent.mouseX - parent.pmouseX;
      int dY = parent.mouseY - parent.pmouseY;
      pickerElement.translate(dX, dY);
    }
  }

  public void dragAll() {
    // Otherwise, these values would be different for every Drawing!
    int dX = parent.mouseX - parent.pmouseX;
    int dY = parent.mouseY - parent.pmouseY;

    for (E element : pickerList) {
      element.translate(dX, dY);
    }
  }

  public void remove() {
    pickerList.remove(pickerElement);

    if (pickerList.isEmpty()) {
      pickerElement = null;
    } else { // Last in pickerList becomes current selection
      int lastIndex = pickerList.size() - 1;
      pickerElement = pickerList.get(lastIndex);
    }
  }

  public void clear() {
    pickerList.clear();
    pickerElement = null;
  }

  /**
   * @throws UnsupportedOperationException if the referenced collection cannot remove elements
   */
  public void delete() {
    elementCollection.remove(pickerElement);
    remove();
  }

  /**
   * @throws UnsupportedOperationException if the referenced collection cannot remove elements
   */
  public void deleteAll() {
    elementCollection.removeAll(pickerList);
    clear();
  }

  public int size() {
    return pickerList.size();
  }

  public boolean isEmpty() {
    return pickerList.isEmpty();
  }

  public Iterator<E> iterator() {
    return pickerList.iterator();
  }

  public ListIterator<E> listIterator() {
    return pickerList.listIterator();
  }

  public ListIterator<E> listIterator(int index) {
    return pickerList.listIterator(index);
  }
}
